'use strict';
const NodeRsa = require('node-rsa');
module.exports = {
  /**
   * 生成回调链接的controller
   * @return {Method} controller
   * @example
   * ```
   * const callback = app.genCallback();
   * router.get('/callback', callback);
   * ```
   */
  genCallback(loginCase, succFuc, errFuc) {
    return async function(ctx) {
      ctx.body = '';
      const {
        serverHost,
        [loginCase]:{
          appId, secret, redirectUri, publicKey,
        } = {},
      } = ctx.app.config.zconnect;
      const { code, state } = ctx.query;
      try {
        if (!ctx.session[loginCase] || `${ctx.session[loginCase].state}` !== state) {
          ctx.logger.warn(`[zconnectLogin] pre: ${ctx.session[loginCase] ? ctx.session[loginCase].state : undefined} now: ${state}`);
          ctx.body = 'state 失效';
          delete ctx.session[loginCase];
          return;
        }
        const url = `${serverHost}/oidc/token`;

        const tokenResult = (await ctx.curl(url, {
          method: 'post',
          data  : {
            code,
            grant_type   : 'authorization_code',
            client_id    : appId,
            client_secret: secret,
            redirect_uri : redirectUri,
          },
          dataType: 'json',
          timeout : 10000,
        })).data;
        const { access_token, id_token } = tokenResult;
        let [header, payload, signature] = id_token.split('.');
        const key = new NodeRsa(publicKey);
        const bol = key.verify(`${header}.${payload}`, signature, 'utf8', 'base64');
        if (!bol) {
          delete ctx.session[loginCase];
          ctx.body = '解析id_token失败';
          return;
        }
        payload = JSON.parse(Buffer.from(payload, 'base64').toString('utf-8'));
        ctx.session[loginCase] = Object.assign(payload, { access_token });
        if(succFuc) {
          return succFuc(ctx);
        }
        ctx.redirect('/');
      } catch (err) {
        delete ctx.session[loginCase];
        ctx.logger.error(`[zconnectLogin] err: ${err}`);
        if(errFuc) {
          return errFuc(ctx);
        }
        ctx.body = 'login error';
      }
    };
  },
};
